﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.SharePoint;
using MS.InformationManagement.Support.Constants;
using Microsoft.SharePoint.Taxonomy;
using System.Text;

namespace MS.InformationManagement.Support
{
    public static class ListHelper
    {
        /// <summary>
        /// Retunr the id for of lists names
        /// </summary>
        /// <param name="listsName"></param>
        /// <returns></returns>
        public static List<string> getListIds(List<string> listsName)
        {
            List<string> listIds = new List<string>();
            using (SPSite currentSite = new SPSite(SPContext.Current.Site.ID))
            {
                using (SPWeb currentWeb = currentSite.OpenWeb())
                {
                    foreach (var listName in listsName)
                    {
                        listIds.Add(currentWeb.Lists[listName].ID.ToString().Replace("{", "").Replace("}", ""));
                    }
                }
            }
            return listIds;
        }

        /// <summary>
        /// Retunr the id for of lists names
        /// </summary>
        /// <param name="listsName"></param>
        /// <returns></returns>
        public static List<string> getListIds(List<string> listsName, SPWeb currentWeb)
        {
            List<string> listIds = new List<string>();
            foreach (var listName in listsName)
            {
                listIds.Add(currentWeb.Lists.TryGetList(listName).ID.ToString().Replace("{", "").Replace("}", ""));
            }
            return listIds;
        }




        public static SPList GetUserList(string loginName)
        {
            SPList userList = null;
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite currentSite = new SPSite(SPContext.Current.Site.ID))
                {
                    using (SPWeb currentWeb = currentSite.OpenWeb())
                    {  
                        if (loginName.Contains('\\'))
                            loginName = loginName.Split('\\')[1];
                        userList = currentWeb.Lists.TryGetList(loginName);
                    }
                }
            });     

            return userList;
        }

        public static string CurrentUserLibraryUrl
        {
            get
            {
                return SPContext.Current.Web.Url + "/" + SPContext.Current.Web.CurrentUser.LoginName.GetUserWithOutDomain();
            }
        }

        public static SPList GetUserListForCurrentUser()
        {
            string userName = SPContext.Current.Web.CurrentUser.LoginName.GetUserWithOutDomain();
            if (SPContext.Current.Web.Lists.TryGetList(userName) == null)
                return null;
            return SPContext.Current.Web.Lists[userName];
        }

        public static E GetItemColumnValueCurrentWeb<E>(string id, string lista, string fieldName)
        {
            SPListItem listItem = GetListItemCurrentWeb(lista, id);
            if (listItem == null) throw new Exception(string.Format(ExceptionConstants.ERROR_LISTA_ITEM_INEXISTENTE, lista, id));
            if (listItem[fieldName] == null)
                return default(E);
            else
                return (E)Convert.ChangeType(listItem[fieldName], typeof(E));
        }

        /// <summary>
        /// Get the value of an specific column in an specific item
        /// </summary>
        /// <typeparam name="E">Type of the value to return</typeparam>
        /// <param name="id">Id of the item to query</param>
        /// <param name="lista">Name of the list to query</param>
        /// <param name="fieldName">Internal name of the field to retrieve</param>
        /// <returns></returns>
        public static E GetItemColumnValue<E>(string id, string lista, string fieldName)
        {
            SPListItem listItem = GetListItem(lista, id, SPContext.Current.Site);
            if (listItem == null) throw new Exception(string.Format(ExceptionConstants.ERROR_LISTA_ITEM_INEXISTENTE, lista, id));
            if (listItem[fieldName] == null)
                return default(E);
            else
                return (E)Convert.ChangeType(listItem[fieldName], typeof(E));
        }

        /// <summary>
        /// Get the an item by its id
        /// </summary>
        /// <param name="lista">Name of the list to query</param>
        /// <param name="id">Id of the item to query</param>
        /// <param name="currentSite">SPSite object of the site wich contains the list</param>
        /// <returns></returns>
        public static SPListItem GetListItem(string lista, string id, SPSite currentSite)
        {
            SPList spLista = currentSite.RootWeb.Lists.TryGetList(lista);
            if (spLista == null) return null;


            SPListItem spItem = spLista.GetItemById(int.Parse(id));
            if (spItem == null) return null;

            return spItem;
        }


        public static SPListItem GetListItemCurrentWeb(string lista, string id)
        {
            SPList spLista = SPContext.Current.Web.Lists.TryGetList(lista);
            if (spLista == null) return null;


            SPListItem spItem = spLista.GetItemById(int.Parse(id));
            if (spItem == null) return null;

            return spItem;
        }

        /// <summary>
        /// Get all the items in a list 
        /// </summary>
        /// <param name="lista">Name of the list to query</param>
        /// <param name="currentSite">Site where the list lives</param>
        public static SPListItemCollection GetAllListItems(string lista, SPWeb currentSite)
        {
            SPList spLista = currentSite.Lists.TryGetList(lista);
            if (spLista == null) return null;

            return spLista.Items;
        }

        /// <summary>
        /// Get absolute uri for a list item
        /// </summary>
        /// <param name="list">List title</param>
        /// <param name="id">id for the list item to query</param>
        /// <returns>Urir</returns>
        public static Uri GetUriForListItem(string list, string id)
        {
            SPListItem listItem = ListHelper.GetListItem(list, id, SPContext.Current.Site);
            if (listItem == null) throw new Exception(string.Format(ExceptionConstants.ERROR_LISTA_ITEM_INEXISTENTE, list, id));
            return new Uri(String.Format("{0}/{1}", listItem.Web.Url, listItem.Url));
        }

        public static void LookUpFieldCreation(string fieldDisplayName, string staticName, string sourceList, string targetList, string contentType, bool multiValue, bool updateChild, SPWeb currentWeb, bool required)
        {

            SPFieldLookup lookup = null;

            //Removing field if exists

            Dictionary<string, string> currentListCollection = new Dictionary<string, string>();
            currentListCollection.Add(sourceList, contentType);
            removeLinkField(fieldDisplayName, staticName, currentWeb, currentListCollection);
            currentWeb.Fields.AddLookup(fieldDisplayName, currentWeb.Lists[targetList].ID, currentWeb.ID, false);
            currentWeb.Update();

            lookup = (SPFieldLookup)currentWeb.Fields[fieldDisplayName];
            lookup.AllowMultipleValues = multiValue;
            lookup.Required = required;
            lookup.LookupField = "Title";
            lookup.Group = "Custom fields";
            lookup.StaticName = staticName;
            lookup.Update();

            //Adding to site content type

            SPContentType siteCt = currentWeb.ContentTypes[contentType];
            siteCt.FieldLinks.Add(new SPFieldLink(lookup));
            if (updateChild)
                siteCt.Update(true);
            else
                siteCt.Update();


            currentWeb.Update();

        }

        public static void LookUpFieldCreation(string fieldDisplayName, string staticName, string sourceList, string targetList, string contentType, string fieldGroup, bool multiValue, bool updateChild, SPWeb currentWeb, bool required)
        {

            SPFieldLookup lookup = null;

            //Removing field if exists

            Dictionary<string, string> currentListCollection = new Dictionary<string, string>();
            currentListCollection.Add(sourceList, contentType);
            removeLinkField(fieldDisplayName, staticName, currentWeb, currentListCollection);
            currentWeb.Fields.AddLookup(fieldDisplayName, currentWeb.Lists[targetList].ID, currentWeb.ID, false);
            currentWeb.Update();

            lookup = (SPFieldLookup)currentWeb.Fields[fieldDisplayName];
            lookup.AllowMultipleValues = multiValue;
            lookup.Required = required;
            lookup.LookupField = "Title";
            lookup.Group = fieldGroup;
            lookup.StaticName = staticName;
            lookup.Update();

            //Adding to site content type

            SPContentType siteCt = currentWeb.ContentTypes[contentType];
            siteCt.FieldLinks.Add(new SPFieldLink(lookup));
            if(updateChild)
                siteCt.Update(true);
            else
                siteCt.Update();


            currentWeb.Update();

        }

        public static void removeLinkField(string fieldDisplayName, string fieldStaticName, SPWeb currentWeb, Dictionary<string, string> lists)
        {

            if (FieldCreationValidation(fieldDisplayName, currentWeb))
            {

                //Deleting from lists

                foreach (KeyValuePair<string, string> list in lists)
                {
                    SPFieldLink field = (from SPFieldLink fieldLink in currentWeb.Lists[list.Key].ContentTypes[list.Value].FieldLinks
                                         where fieldLink.Name.Equals(fieldStaticName)
                                         select fieldLink).SingleOrDefault();
                    if (field != null)
                    {
                        currentWeb.Lists[list.Key].ContentTypes[list.Value].FieldLinks.Delete(field.Id);
                        currentWeb.Lists[list.Key].ContentTypes[list.Value].Update();
                        currentWeb.Lists[list.Key].Update();
                    }

                }

                //Deleting from site 

                if (currentWeb.Fields.ContainsFieldWithStaticName(fieldStaticName))
                    currentWeb.Fields.Delete(fieldDisplayName);

                currentWeb.Update();

            }

        }

        public static bool FieldCreationValidation(string fieldDisplayName, SPWeb currentWeb)
        {

            //Removing from web

            var Countryfield = (from f in currentWeb.Fields.Cast<SPField>()
                                where f.Title.Equals(fieldDisplayName)
                                select f);

            if (Countryfield.Count() > 0)
                return true;
            else
                return false;

        }

        public static void MakeFieldUnique(SPWeb web, string listName, Guid fieldId)
        {
            web.AllowUnsafeUpdates = true;
            SPList targetList = web.Lists.TryGetList(listName);
            SPField targetField = targetList.Fields[fieldId];
            targetField.Indexed = true;
            targetField.EnforceUniqueValues = true;
            targetField.Update();
            web.AllowUnsafeUpdates = false;
        }

        public static void MakeFieldRequired(SPWeb web, string listName, Guid fieldId)
        {
            web.AllowUnsafeUpdates = true;
            SPList targetList = web.Lists.TryGetList(listName);
            SPField targetField = targetList.Fields[fieldId];
            targetField.Indexed = true;
            targetField.Required = true;
            targetField.Update();
            web.AllowUnsafeUpdates = false;
        }

        /// <summary>
        /// Attach a file collection of files to a list item
        /// </summary>
        /// <param name="listItem">Listitem where files will be attached</param>
        /// <param name="files">Dictionarity with keypairs string,byte array with files to be attached</param>
        public static void AttachFilesToListItem(SPListItem listItem, Dictionary<string, byte[]> files)
        {
            foreach (var fileEntry in files)
            {
                listItem.Attachments.Add(fileEntry.Key, fileEntry.Value);
                listItem.SystemUpdate();
            }
        }

        /// <summary>
        /// Get url for insert form new list item in a list in the current web
        /// </summary>
        /// <param name="listTitle">Title of the list to query</param>
        /// <returns></returns>
        public static string GetUrlForNewItemList(string listTitle)
        {
            return SPContext.Current.Web.Lists[listTitle].DefaultNewFormUrl;
        }

        public static bool ConvertToBoolean(string value)
        {
            try
            {
                return Convert.ToBoolean(value);
            }
            catch (FormatException)
            {
                return false;
            }
        }

        public static int TryToParse(string value)
        {
            int number;
            bool result = Int32.TryParse(value, out number);
            if (result)
            {
                return number;
            }
            else
            {
                return 0;
            }
        }

        public static void AddFieldLookupInView(string fieldDisplayName, SPWeb currentWeb, string sourceList)
        {
            SPList list = currentWeb.Lists.TryGetList(sourceList);
            if (list != null)
            {
                currentWeb.AllowUnsafeUpdates = true;
                SPFieldLookup lookup = (SPFieldLookup)list.Fields.GetFieldByInternalName(fieldDisplayName);
                SPView view = list.DefaultView;
                view.ViewFields.Add(lookup);
                view.Update();

                currentWeb.Update();
                currentWeb.AllowUnsafeUpdates = false;
            }
        }

        #region Taxonomy Methods

        /// <summary>
        /// This Method attach a taxonomy property to a taxonomy site field
        /// </summary>
        /// <param name="group">Taxonomy Group</param>
        /// <param name="termSetName">TermSet Name</param>
        /// <param name="fieldId">Field site id</param>
        /// <param name="currentWeb">SPWeb web object where field is located</param>
        /// <param name="multipleValues">Define if the taxonomy field could have multiple values</param>
        /// <param name="HiddenTextControl">GUID of the hidden note text field where the primary field save the selected values</param>


        #endregion

    }
}
